#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<queue>
#include<time.h>
#include<string>
#include<cstring>
#include<sys/types.h>
#include "BlockQueue.hpp"
#include "Task.hpp"

std::string opstr = "+-*/%";

// op是运算符

int mycal(int x,int y,char op)
{   
    switch (op)
    {
        case '+':
        return x + y;

        case '-':
        return x - y;

        case '*':
        return x * y;

        case '/':
        {
            if(y == 0)
            {
                std::cout << "除零错误" << std::endl;
                return -999;
            }
            else
            {
                return x / y;
            }
        }

        case '%':
        {
            if(y == 0)
            {
                std::cout << "除零错误" << std::endl;
                return -999;
            }
            else
            {
                return x % y;
            }
        }

        default :
        return -1;
    };
}


void* consumer(void* arvg)
{
    // 先安全的强制转换一下
//    BlockQueue<Task>* BQ = static_cast<BlockQueue<Task>*>(arvg);
    BlockQueue<Task>* BQ = static_cast<BlockQueueS<Task,std::string>*>(arvg)->_bq1;
    BlockQueue<std::string>* Save_bq = static_cast<BlockQueueS<Task,std::string>*>(arvg)->_bq2;
    while(1)
    {
       Task getdata;
       BQ->pop(&getdata);
       
       //std::cout << "执行任务myadd  = " << getdata() << std::endl; 
       int result = getdata();

       printf("%d %c %d = %d\n",getdata._x,getdata._op,getdata._y,result);

       // 把任务发送给保存管道
      char buffer[1024];
      snprintf(buffer,sizeof(buffer), "%d %c %d = %d", getdata._x , getdata._op ,getdata._y,result);
      std::string save = buffer;
      Save_bq->push(save);
      sleep(1);
    }
}

void* producer(void* arvg)
{
   // BlockQueue<Task>* BQ = static_cast<BlockQueue<Task>*>(arvg);
    // arvg变量先强转回来，然后指向_bq1
    
    BlockQueue<Task>* BQ = static_cast<BlockQueueS<Task,std::string>*>(arvg)->_bq1;
    // 操作第一个阻塞队列即可
    while(1)
    {
        //生产更乱的随机数
        srand((unsigned int)time(nullptr) ^ getpid() );
        //srand((unsigned long)time(nullptr) ^ getpid() ); ? 

        int x = rand()  % 10  +  1;
        int y = rand()  % 10  + 1 ;
        int index = rand() % 5 ;

        Task task(x, y ,opstr[index],mycal);

        BQ->push(task);

        char buffer[1024];
        snprintf(buffer,sizeof(buffer), "%d %c %d = ?", x , opstr[index] ,y);
        std::cout << buffer << std::endl;
        //注意 snprintf 和 sprintf

        //std::cout << "我生产了一个任务 x = " << x  << " y = " << y << std::endl;
        //我每隔一秒发送一个信息，达到了 生产和消费不均，体现出队列的作用
        //sleep(1);
    }
}

void *save(void* arvgs)
{
     BlockQueue<std::string>* save_bq = static_cast<BlockQueueS<Task,std::string>*>(arvgs)->_bq2;
    
     while(1)
     {
        FILE* file;
        file = fopen("log.txt","a+");

        std::string str;
        save_bq->pop(&str);
        std::cout << "我是save线程，我将向文件写入 ：" << str <<std::endl;

        fprintf(file,str.c_str());
        fprintf(file,"\n");
        
        fclose(file);

        sleep(1);
     }
}

int main()
{
    pthread_t t1,t2,t3;
    //BlockQueue<Task> BQ;

    // 保存的一个Task队列，一个string队列

    //BlockQueue<Task>  bq1;
    //BlockQueue<std::string> bq2;
    //BlockQueueS<BlockQueue<Task>,BlockQueue<std::string>> BQ(bq1,bq2);

    BlockQueueS<Task,std::string> BQ;
    BQ._bq1 = new BlockQueue<Task>();
    BQ._bq2 = new BlockQueue<std::string>();

    pthread_create(&t1,nullptr,consumer,&BQ);
    pthread_create(&t2,nullptr,producer,&BQ);
    pthread_create(&t3,nullptr,save,&BQ);

    while(1);

    pthread_join(t1,nullptr);
    pthread_join(t2,nullptr);
    pthread_join(t3,nullptr);

    return 0;
}